<?php
//
// +------------------------------------------------------------------------+
// | Gecko Framework                                                        |
// +------------------------------------------------------------------------+
//
require_once('Gecko/Form/Field/Interface.php');
require_once('Zend/Validate.php');
/**
 * Abstract Base Field for Form controls
 *
 * @package Gecko.Form;
 * @author Christopher Valderrama <valderrama.christopher@gmail.com>
 * @copyright Copyright (c) 2008
 * @version $Id$v1.0$ 2008
 * @access public
 **/
abstract class Gecko_Form_Field implements Gecko_Form_Field_Interface {
	/**
	 * The Field Name
	 *
	 * @var string
	 */
	private $name;

	/**
	 * The Field default initial value
	 *
	 * @var string
	 */
	private $defaultValue;

	/**
	 * The field Value
	 *
	 * @var string
	 */
	private $value;

	/**
	 * The field parameters
	 *
	 * @var array
	 */
	private $params = array();

	/**
	 * Field Validators
	 *
	 * @var string
	 */
	private $validators = array();

	/**
	 * The Field Type
	 *
	 * @access protected
	 * @var string
	 */
	protected $type = 'field';

	/**
	 * Creates a static field given the type and params using the
	 * Factory pattern
	 *
	 * @param $type The type of the field
	 * @param $name The name for the field
	 * @param $value The default value
	 * @param $parameters The parameters of the field
	 * @return Gecko_Form_Field object
	 **/
	public static function factory( $type, $name, $value = '', $params = array() ) {
		$type = "Gecko_Form_Field_" . ucfirst( $type );

		Zend_Loader::loadClass( $type );

		$obj = new $type( $name, $value, $params );
		return $obj;
	}

	/**
	 * Creates a new Form Field (since class is abstract can't
	 * be constructed), so you must extend the class.
	 *
	 * @param string $name The Control Name
	 * @param string $value The default control Value
	 * @param array $params The specific control parameters
	 * @access public
	 * @return string The Value of the Control
	 */
	public function __construct( $name, $value = "", $params = array() ) {
		$this->name = $name;
		$this->defaultValue = $value;
		$this->value = $value;
		$this->params = $params;
	}

	/**
	 * Gets the control type
	 *
	 * @return string
	 */
	public function getType() {
		return $this->type;
	}

	/**
	 * Returns the control javascript if it's needed
	 *
	 * @access public
	 * @return string The code
	 */
	public function getJavascriptCode() {
		return "";
	}

	/**
	 * Returns the control name
	 *
	 * @access public
	 * @return string The Name of the Control
	 */
	public function getName() {
		return $this->name;
	}

	/**
	 * Returns the current control Value
	 *
	 * @access public
	 * @return string The Value of the Control
	 */
	public function getValue() {
		return $this->value;
	}

	/**
	 * Returns the field default value (if set)
	 *
	 * @return mixed
	 */
	public function getDefaultValue() {
		return $this->defaultValue;
	}

	/**
	 * Sets the new control value
	 *
	 * @param $value The control Value
	 * @access public
	 * @return string The Value of the Control
	 */
	public function setValue( $value ) {
		$this->value = $value;
	}

	/**
	 * Gets the control Parameters
	 *
	 * @access public
	 * @return array of params
	 */
	public function getParams() {
		return $this->params;
	}

	/**
	 * Adds a new Validator to the control
	 *
	 * @param $validator The validator to add
	 * @access public
	 * @return self instance for chaining
	 */
	public function addValidator(Zend_Validate_Interface $validator, $breakChainOnFailure = false) {
		if( !($validator instanceof Zend_Validate_Interface ) ) {
			throw new Gecko_Form_Exception('$validator doesn\'t inteface Zend_Validate_Interface');
		}

		 $this->validators[] = array(
            'instance' => $validator,
            'breakChainOnFailure' => (boolean) $breakChainOnFailure
            );

		return $this;
	}

	/**
	 * Clears the registered validators
	 *
	 * @access public
	 * @return void
	 */
	public function clearValidators() {
		$this->validators = array();
	}

	/**
	 * Validates the control against the validator set
	 *
	 * @param $formValues array
	 * @access public
	 * @return object The result of the control
	 */
	public function isValid($formValues) {
		$result = true;
		$messages = array();

		foreach($this->validators as $validator) {
			if(!$validator->isValid($this->getValue(), $formValues)) {
				$result = false;
				$messages = array_merge($messages, $validator->getMessages());
			}
		}

		$rst = new Gecko_Form_Result( $result, $messages );
		return $rst;
	}

	/**
	 * Returns the JavaScript validation code
	 *
	 * @access public
	 * @return object The The JSON array to pass to the JS validator
	 */
	public function getJavascriptValidationCode() {
		$json = array();
		foreach($this->validators as $validator) {
			if( $validator['instance'] instanceof Gecko_Form_Validator_Interface ) {
				$json[] = $validator['instance']->getJSONValidationCode();
			}
		}

		if( count( $json ) > 0 ) {
			$json = "{" . implode( ",", $json) . "}";
		} else {
			$json = "";
		}

		return $json;
	}

	/**
	 * Returns the control to draw on web page (html).
	 *
	 * @access public
	 * @return string The The Control
	 */
	abstract public function getControl();

	/**
	 * To String implementation
	 *
	 * @return string
	 */
	public function __toString() {
		return $this->getControl();
	}
}